/*
 * Copyright (C) 2011 Nicolas BARBOTIN
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "GUI.h"
#include <iostream>

SDL_Surface *getGFXByState(GUI_GFX gfx, GUI_State state) {
    switch(state) {
        case GUIS_Normal:
            return gfx.gfx_normal;
            break;

        case GUIS_Disabled:
            return gfx.gfx_disabled;
            break;

        case GUIS_Over:
            return gfx.gfx_over;
            break;

        case GUIS_Pressed:
            return gfx.gfx_pressed;
            break;
    }
}

GUI_Button GUI_CreateButton(SDL_Rect position, GUI_GFX graphics) {
    GUI_Button button;
    button.position = position;
    button.graphics = graphics;
    button.state = GUIS_Normal;
    button.clicked = false;

    return button;
}

GUI_Button GUI_CreateButton(int x, int y, GUI_GFX graphics) {
    SDL_Rect pos;
    pos.x = x;
    pos.y = y;

    return GUI_CreateButton(pos, graphics);
}

void GUI_Update(GUI_Button *button, SDL_Event event) {
    if(button->clicked)
        button->clicked = false;

    if(button->state == GUIS_Disabled)
        return;

    if(event.motion.x >= button->position.x && event.motion.x <= button->position.x + getGFXByState(button->graphics, button->state)->w &&
       event.motion.y >= button->position.y && event.motion.y <= button->position.y + getGFXByState(button->graphics, button->state)->h) {

        if(event.button.button == SDL_BUTTON_LEFT && event.button.state == SDL_PRESSED) {
            button->state = GUIS_Pressed;
            return;
        } else {
            if(button->state == GUIS_Pressed)
                button->clicked = true;

            button->state = GUIS_Over;
            return;
        }
    }

    button->state = GUIS_Normal;
    return;
}

void GUI_Draw(GUI_Button button, SDL_Surface *screen) {
    SDL_BlitSurface(getGFXByState(button.graphics, button.state), NULL, screen,  &button.position);
}

GUI_DraggableObject GUI_CreateDraggable(SDL_Rect position, GUI_GFX graphics, bool onlyDropInDropAreas, SDL_Rect *dropAreas, int dropAreasCount) {
    GUI_DraggableObject draggable;
    draggable.position = position;
    draggable.origin = position;
    draggable.graphics = graphics;
    draggable.state = GUIS_Normal;
    draggable.onlyDropInDropAreas = onlyDropInDropAreas;
    draggable.dropAreas = dropAreas;
    draggable.isDragging = false;
    draggable.dropAreasCount = dropAreasCount;
    draggable.hasKey = false;
    draggable.origin2 = position;

    return draggable;
}

GUI_DraggableObject GUI_CreateDraggable(int x, int y, GUI_GFX graphics, bool onlyDropInDropAreas, SDL_Rect *dropAreas, int dropAreasCount) {
    SDL_Rect pos;
    pos.x = x;
    pos.y = y;

    return GUI_CreateDraggable(pos, graphics, onlyDropInDropAreas, dropAreas, dropAreasCount);
}

void GUI_Update(GUI_DraggableObject *draggable, SDL_Event event) {
    if(draggable->state == GUIS_Disabled)
        return;

    if(draggable->isDragging) {
        if(event.button.type == SDL_MOUSEBUTTONUP) {
            if(draggable->onlyDropInDropAreas) {
                int i = 0;
                int validPlace = -1;

                while(i < draggable->dropAreasCount) {
                    if(event.motion.x >= draggable->dropAreas[i].x && event.motion.x <= draggable->dropAreas[i].x + draggable->dropAreas[i].w &&
                   event.motion.y >= draggable->dropAreas[i].y && event.motion.y <= draggable->dropAreas[i].y + draggable->dropAreas[i].h) {
                        validPlace = i;
                    }

                    i++;
                }

                if(validPlace != -1) {
                    draggable->position.x = draggable->dropAreas[validPlace].x;
                    draggable->position.y = draggable->dropAreas[validPlace].y;
                    //draggable->origin = draggable->position;
                } else {
                    draggable->position.x = draggable->origin.x;
                    draggable->position.y = draggable->origin.y;
                }
            }
            draggable->isDragging = false;
            return;
        }

        draggable->position.x = event.motion.x - draggable->mousePosOnClick.x;
        draggable->position.y = event.motion.y - draggable->mousePosOnClick.y;
        return;
    }

    if(event.motion.x >= draggable->position.x && event.motion.x <= draggable->position.x + getGFXByState(draggable->graphics, draggable->state)->w &&
       event.motion.y >= draggable->position.y && event.motion.y <= draggable->position.y + getGFXByState(draggable->graphics, draggable->state)->h) {
        if(event.button.button == SDL_BUTTON_LEFT && event.button.state == SDL_PRESSED) {
            draggable->mousePosOnClick.x = event.motion.x - draggable->position.x;
            draggable->mousePosOnClick.y = event.motion.y - draggable->position.y;
            draggable->isDragging = true;
            draggable->state = GUIS_Pressed;
            return;
        } else {
            draggable->state = GUIS_Over;
            return;
        }
    }

    draggable->state = GUIS_Normal;
    return;
}

void GUI_Draw(GUI_DraggableObject draggable, SDL_Surface *screen) {
    SDL_BlitSurface(getGFXByState(draggable.graphics, draggable.state), NULL, screen, &draggable.position);
}
